import { createElements, define, itag } from "../itag/index.js";
import { formatSize, type SizeFormat } from "../SizeFormat.js";
import type { IRequestFieldElement } from "./IFieldElement.js";
import { RangeElement } from "./RangeElement.js";
import type { EnumRequestFieldOption } from "./RequestOption.js";
import * as styles from "./styles.js";

export class EnumRequestFieldElement extends HTMLElement implements IRequestFieldElement {
    /**
     * 枚举表
     */
    #enums: Record<string, number> = {};

    readonly #elms = createElements({
        enumName: "span",
        value: "span", // 当前值
        options: "div", // 下拉选项
        name: "span", // 字段名
        range: RangeElement, // 区间
    });

    /**
     * 枚举自身的大小
     */
    #size: SizeFormat = 1;

    /**
     * 当前值
     */
    #value: number | null = null;

    constructor() {
        super();
        itag`
${this} .${styles.field}
    div .${styles.enumAll}
        div
            ${this.#elms.value}   .value
            ${this.#elms.enumName} .enumName
        ${this.#elms.options} .options
    ${this.#elms.name}   .${styles.name}
    ${this.#elms.range} 
`;
    }

    /**
     * 添加下拉选项
     * @param name  下拉选项名称
     * @param value 下拉选项的实际值
     */
    #addItem(name: string, value: number): void {
        this.#enums[name] = value;
        const elm = document.createElement("div");
        elm.textContent = name;
        elm.addEventListener("click", (e) => {
            e.stopPropagation();
            e.preventDefault();
            this.#setValue(value);
        });
        this.#elms.options.appendChild(elm);
    }

    get option(): EnumRequestFieldOption {
        return {
            name: this.#elms.name.textContent ?? "",
            kind: "enum",
            value: this.#value ?? undefined,
            enums: this.#enums,
            size: this.#size,
        };
    }

    set option(value: EnumRequestFieldOption) {
        this.#elms.name.textContent = value.name;
        this.#size = value.size ?? 1;
        this.#enums = {};
        for (const [key, val] of Object.entries(value.enums ?? {})) {
            this.#addItem(key, val);
        }
        this.#setValue(value.value);
        this.#elms.range.length = this.#size;
        this.dispatchEvent(new Event("change"));
    }

    get name(): string {
        return this.#elms.name.textContent ?? "";
    }

    data(): number[] {
        if (this.#value === null) {
            throw new Error("250409174112393, value is null");
        }
        return formatSize(this.#size, this.#value);
    }

    setBegin(begin: number): void {
        this.#elms.range.begin = begin;
    }

    #setValue(value?: number | undefined): void {
        if (value === undefined) {
            if (this.#value === null) {
                return;
            }
            this.#value = null;
            this.#elms.value.textContent = "";
            return;
        }
        if (this.#value === value) {
            return;
        }
        for (let name in this.#enums) {
            if (this.#enums[name] === value) {
                this.#value = value;
                this.#elms.value.textContent = this.#value
                    .toString(16)
                    .padStart(this.#size * 2, "0")
                    .toUpperCase();
                this.#elms.enumName.textContent = name;
                this.#elms.value.title = this.#value.toString();
                return;
            }
        }
        throw new Error(`250409174112393, value ${value} is not in enums, enums: ${JSON.stringify(this.#enums)}`);
    }

    byteLength(): number {
        return this.#size;
    }
}

define(EnumRequestFieldElement);
